module top;
   import uvm_pkg::*;
   typedef class class_A;

   // Class definition
class class_A extends uvm_object;

   int cl_int;
   string cl_string;
   int 	  cl_int_arr[];
   `uvm_object_utils_begin(class_A)
      `uvm_field_int(cl_int,UVM_ALL_ON);
      `uvm_field_string(cl_string,UVM_ALL_ON);
      `uvm_field_array_int(cl_int_arr,UVM_ALL_ON);
   `uvm_object_utils_end
   
   function new(string name="",int value);
      super.new(name);	
      cl_string = name;
      cl_int = value;
      cl_int_arr = new[cl_int];
      for(int i = 0; i < cl_int; i++) begin
	 cl_int_arr[i] = i + 1;
      end
   endfunction

endclass

   
class  class_P extends uvm_object;

   // basic datatypes
   rand int par_int; 
   rand byte par_address;
   string par_string;

   // Some objects to demonstrate the copy recursion policy

   class_A cl1; // UVM_SHALLOW
   class_A cl3; // UVM_DEEP

   `uvm_object_utils_begin(class_P)
      `uvm_field_int(par_int,UVM_ALL_ON)
      `uvm_field_int(par_address,UVM_ALL_ON | UVM_NOCOPY)
      `uvm_field_string(par_string,UVM_NOCOPY)
      `uvm_field_object(cl1,UVM_ALL_ON|UVM_NOCOPY)
      `uvm_field_object(cl3,UVM_ALL_ON | UVM_NOCOPY)
   `uvm_object_utils_end

   function new(string name="",int inst_id);
      super.new(name);
      cl1 = new(name,inst_id );
      cl3 = new(name,inst_id +1 )	;
      par_string  = name;
   endfunction
   
   function void do_copy(uvm_object rhs);
      class_P rhs_;
      super.do_copy(rhs);
      $cast(rhs_,rhs);
      par_int = rhs_.par_int;
      par_address = rhs_.par_address;
      par_string = rhs_.par_string;
      cl1 = new rhs_.cl1;
      cl3 = new rhs_.cl3;
      cl1.copy(rhs_.cl1);
      cl3.copy(rhs_.cl3);
   endfunction


endclass

   

   class_P  class_P_inst1;
   class_P  class_P_inst2;
   class_A    class_A_inst1;
   class_A    class_A_inst2;
   initial begin
      // free children
      class_A_inst1 = new("child_inst1",1);
      class_A_inst2 = new("child_inst3",3);



      class_P_inst1 = new("first_inst",1);
      class_P_inst1.randomize();
      class_P_inst1.print();
      
      class_P_inst2 = new("second_inst",2);
      class_P_inst2.randomize();
      class_P_inst2.print();


      class_P_inst2.copy(class_P_inst1);
      class_P_inst2.print();

   end 
endmodule
